package com.itaming.lycheeframework.validation.validators;

import com.itaming.lycheeframework.support.utils.ArrayUtil;
import com.itaming.lycheeframework.support.utils.ObjectUtil;
import com.itaming.lycheeframework.support.utils.ReflectionUtil;
import com.itaming.lycheeframework.validation.annotation.ValidationEnumField;
import com.itaming.lycheeframework.validation.constraints.EnumValue;
import com.itaming.lycheeframework.validation.interfaces.ValidatableEnum;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import org.springframework.util.ObjectUtils;

import java.lang.reflect.Field;
import java.util.Objects;

/**
 * 枚举值校验类
 *
 * @author A.Ming
 */
public class EnumValueValidator implements ConstraintValidator<EnumValue, Object> {

    /**
     * 校验注解
     */
    private EnumValue annotation;

    @Override
    public void initialize(EnumValue annotation) {
        this.annotation = annotation;
    }

    @Override
    @SuppressWarnings("unchecked")
    public boolean isValid(Object fieldValue, ConstraintValidatorContext constraintValidatorContext) {
        // 空值用 NotNull 和 NotEmpty 校验
        if (ObjectUtil.isEmpty(fieldValue)) {
            return true;
        }

        // 获取枚举
        Class<? extends Enum<?>> enumClass = annotation.value();

        // 枚举是 ValidatableEnum 实现类
        if (ValidatableEnum.class.isAssignableFrom(enumClass)) {
            return handleValidatableEnum((Class<? extends ValidatableEnum<?>>) enumClass, fieldValue);
        }

        // 遍历字段，查找注解
        return handleAnnotatedField(enumClass, fieldValue);
    }

    /**
     * 处理 ValidatableEnum 实现类
     *
     * @param enumClass  枚举类
     * @param fieldValue 字段值
     * @return boolean
     */
    private boolean handleValidatableEnum(Class<? extends ValidatableEnum<?>> enumClass, Object fieldValue) {
        ValidatableEnum<?>[] enumConstants = enumClass.getEnumConstants();
        if (ObjectUtils.isEmpty(enumConstants)) {
            return false;
        }

        for (ValidatableEnum<?> enumConstant : enumConstants) {
            if (Objects.equals(enumConstant.getValue(), fieldValue)) {
                return true;
            }
        }

        return false;
    }

    /**
     * 处理注解字段
     *
     * @param enumClass  枚举类
     * @param fieldValue 字段值
     * @return boolean
     */
    private boolean handleAnnotatedField(Class<? extends Enum<?>> enumClass, Object fieldValue) {
        Field field = ReflectionUtil.findField(enumClass, ValidationEnumField.class);
        if (field == null) {
            return true;
        }

        Enum<?>[] enumConstants = enumClass.getEnumConstants();
        if (ArrayUtil.isNotEmpty(enumConstants)) {
            for (Enum<?> enumConstant : enumConstants) {
                if (Objects.equals(ReflectionUtil.getFieldValue(field, enumConstant), fieldValue)) {
                    return true;
                }
            }
        }

        return false;
    }

}
